#include "../handler_task.h"
#include "../../service/salve_conn.h"
#include "../../conn/proto.h"
#include "./draw_task.h"
#include "./make_ice_task.h"
#include "../../driver/ice/parts.h"
#include "../../driver/ice/stir_motor.h"
#include "../../service/ice/pick_service.h"

namespace task {

using namespace service;
using namespace utils;
using namespace conn;
using namespace driver;

static Error on_draw_ctrl(const Message &msg) {
    uint8_t type;
    Error err = msg.parse(type);
    if (err) {
        goto finish;
    }
    switch (type) {
        case 0: drawTask->draw_auto(); break;
        case 1: drawTask->draw_stop(); break;
        case 2: drawTask->draw_open(); break;
        default: err = ec::INVALID;
    }
finish:
    return err;
}

static Error on_make_ctrl(const Message &msg) {
    uint8_t type;
    Error err = msg.parse(type);
    if (err) {
        goto finish;
    }
    switch (type) {
        case 0: makeIceTask->auto_make(); break;
        case 1: makeIceTask->stop(); break;
        default: err = ec::INVALID; break;
    }
finish:
    return err;
}

static Error on_parts_ctrl(const Message &msg) {
    uint8_t type, ctrl;
    uint16_t val;
    Error err = msg.parse(type, ctrl);
    if (err) {
        goto finish;
    }
    val = (type << 8) + ctrl;
    switch (val) {
        case 0x0100: parts->open_fan(); break;
        case 0x0101: parts->close_fan(); break;

        case 0x0200: parts->open_valve(); break;
        case 0x0201: parts->close_valve(); break;

        case 0x0300: parts->open_pump(); break;
        case 0x0301: parts->close_pump(); break;

        case 0x0400: parts->open_drop_ice(); break;
        case 0x0401: parts->close_drop_ice(); break;

        case 0x0500: stirMotor->open(); break;
        case 0x0501: stirMotor->close_once(); break;

        default: err = ec::INVALID; break;
    }
finish:
    return err;
}

static Error on_drop_ice(const Message &msg) {
    uint8_t sec;
    Error err = msg.parse(sec);
    if (err) {
        goto finish;
    }
    err = drop_ice(sec);
finish:
    return err;
}

void HandlerTask::dispatch_impl(const Message &msg) {

    Error err;

    switch (msg.conn_info.req) {
        
        case proto::REQ_ICE_DRAW_CTRL: 
            err = on_draw_ctrl(msg); 
        break;

        case proto::REQ_ICE_MAKE_CTRL:
            err = on_make_ctrl(msg);
        break;

        case proto::REQ_ICE_PARTS_CTRL:
            err = on_parts_ctrl(msg);
        break;

        case proto::REQ_ICE_DROP_ICE:
            err = on_drop_ice(msg);
        break;

        default:
            err = ec::INVALID;
        break;
    }
    salveConn->response(msg, err);
}

}
